package com.iisigroup.adrclient.app;

import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.text.DefaultCaret;

import net.miginfocom.swing.MigLayout;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

import com.iisigroup.adrclient.common.DateUtils;
import com.iisigroup.adrclient.common.GenericObject;
import com.iisigroup.adrclient.common.PartAddress;
import com.iisigroup.adrclient.service.AdrClientService;
import com.iisigroup.adrclient.service.StreetBlockService;
import com.iisigroup.adrclient.vo.StreetBlockVO;

@Component
public class AdrClientApp extends GenericObject implements Runnable {
	private static final Integer YEAR_DIFF = 1911;
	private static final String OUTPUT_PATH = new File("").getAbsolutePath().toString() + "/output/";
	
	private final JFrame frame = new JFrame("AddrClient");
	private final JPanel main = new JPanel(new MigLayout("insets 5 5 5 5, h 500, w 500"));
	private final JLabel banner = new JLabel(new ImageIcon(Thread.currentThread().getContextClassLoader().getResource("banner.jpg")));
	private final JTextArea console = new JTextArea();
	private final JScrollPane consolePane = new JScrollPane();
	private final JPanel panel1 = new JPanel(new MigLayout());
	private final JPanel panel2 = new JPanel(new MigLayout());
	private final JPanel panel3 = new JPanel(new MigLayout());
	private final JPanel panel4 = new JPanel(new MigLayout());
	private final JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
	private final JProgressBar progress = new JProgressBar(0, 100);
	private final Calendar calendar = Calendar.getInstance();
	private Map<String, String> countyMap = null;
	private Long startTime = 0L;
	private Long endTime = 0L;
	private String sourceUrl = null;
	private String targetUrl = null;
	private SwingWorker<Void, Void> worker = null;
	
	@Autowired
	private AdrClientService service;
	
	@Autowired
	private StreetBlockService sbService;
	
	private enum Label {
		BUTTON_OUTPUT_150("產製鄰街廓"),
		BUTTON_OUTPUT_168("產製村里街廓"),
		BUTTON_OUTPUT_220("產製工商街廓"),
		BUTTON_OUTPUT_260("產製地址明細"),
		BUTTON_OUTPUT_270("產製戶籍明細"),
		BUTTON_OUTPUT_POST("產製POST"),
		BUTTON_OUTPUT_SPRD("產製特殊路街"),
		BUTTON_OUTPUT_AREA("產製村里代碼"),
		BUTTON_OUTPUT_CITY("產製縣市代碼"),
		PANEL_1("地址分欄"),
		PANEL_2("產製參考檔"),
		PANEL_3("驗證檔案"),
		PANEL_4("建立街廓檔"),
		BUTTON_UPLOAD_200("上傳門牌"),
		BUTTON_UPLOAD_250("上傳戶籍"),
		BUTTON_TO_380("建立地址分欄結果"),
		BUTTON_COMPARE_150("比較鄰街廓"),
		BUTTON_COMPARE_168("比較村里街廓"),
		BUTTON_COMPARE_260("比較地址明細"),
		BUTTON_COMPARE_270("比較戶籍明細"),
		BUTTON_SOURCE("來源檔案"),
		BUTTON_TARGET("比較檔案"),
		BUTTON_UPLOAD_POST("上傳POST"),
		BUTTON_UPLOAD_POST2("上傳POST2"),
		BUTTON_UPLOAD_AREA("上傳村里代碼"),
		BUTTON_UPLOAD_SPRD("上傳特殊路街"),
		BUTTON_COMPARE_POST("比較POST"),
		BUTTON_COMPARE_AREA("比較村里代碼"),
		BUTTON_COMPARE_SPRD("比較特殊路街"),
		BUTTON_CREATE_220("建立工商街廓資料"),
		BUTTON_INIT_220("建立工商街廓資料(以100年為母體)"),
		BUTTON_CREATE_150("建立鄰街廓"),
		BUTTON_CREATE_168("建立村里街廓"),
		BUTTON_OUTPUT_380("產製地址分欄結果"),
		BUTTON_OUTPUT_150NEW("產製鄰街廓(新)"),
		BUTTON_OUTPUT_168NEW("產製村里街廓(新)"),
		BUTTON_OUTPUT_WORD_MAP("產製異陳字"),
		BUTTON_UPLOAD_WORD_MAP("上傳異陳字");
		private final String value;
		private Label(String value) {
			this.value = value;
		}
		@Override
		public String toString() {
			return this.value;
		}
	}
	
	@Override
	public void run() {
		init();
	}
	
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
		AdrClientApp app = context.getBean(AdrClientApp.class);
		SwingUtilities.invokeLater(app);
	}
	
	private void init() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			this.logError(e);
		}
		countyMap = service.getCountyMap();
		
		setMain();
		setTabbedPane();
		setPanel1();
		setPanel2();
		setPanel3();
		setPanel4();
	    
		frame.setSize(500, 500);
		frame.setLocationByPlatform(true);
		frame.setResizable(false);
	    frame.add(main);
	    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	    frame.pack();
	    frame.setVisible(true);
	}
	
	private void setMain() {
		console.setRows(10);
		console.setBorder(BorderFactory.createTitledBorder("Console"));
		console.setEditable(false);
		((DefaultCaret) console.getCaret()).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
		consolePane.setViewportView(console);
		consolePane.setAutoscrolls(true);
		
		main.add(banner, "w 100%, dock north");
	    main.add(tabbedPane, "w 100%, h 60%, wrap");
	    main.add(consolePane, "w 100%, h 35%, wrap");
	    main.add(progress, "w 100%, h 5%");
	}
	
	private void setTabbedPane() {
		tabbedPane.addTab(Label.PANEL_1.toString(), panel1);
		tabbedPane.addTab(Label.PANEL_4.toString(), panel4);
	    tabbedPane.addTab(Label.PANEL_2.toString(), panel2);
	    tabbedPane.addTab(Label.PANEL_3.toString(), panel3);
	}
	
	private void setPanel1() {
		final JPanel panelTop1 = new JPanel(new MigLayout());
		panelTop1.setBorder(BorderFactory.createTitledBorder("年份"));
		Integer currentYear = calendar.get(Calendar.YEAR) - YEAR_DIFF;
		final JComboBox<String> cbYear = new JComboBox<String>();
		for (Integer year = currentYear - 4; year <= currentYear + 10; year++) {
			cbYear.addItem(year.toString());
		}
		cbYear.setSelectedItem(currentYear.toString());
		panelTop1.add(cbYear, "w 100%");
		
		final JPanel panelTop2 = new JPanel(new MigLayout());
		panelTop2.setBorder(BorderFactory.createTitledBorder("縣市"));
		final JComboBox<String> cbCounty = new JComboBox<String>();
		for (String key : countyMap.keySet()) {
			cbCounty.addItem(key);
		}
		panelTop2.add(cbCounty, "w 100%");
		
		final JPanel panelBot1 = new JPanel(new MigLayout());
		panelBot1.setBorder(BorderFactory.createTitledBorder("上傳檔案"));
		
		final JButton btnUpload200 = new JButton(Label.BUTTON_UPLOAD_200.toString());
		
		btnUpload200.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						String url = getFile().getAbsolutePath();
						progress.setIndeterminate(true);
						if (url != null && (service.countAdr200(year, countyCode) == 0 || JOptionPane.showConfirmDialog(frame, "資料庫已有" + year + "年的資料，確定要重新上傳？", "確認上傳", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == 0)) {
							startTime = System.currentTimeMillis();
							service.uploadAdr200(year, countyCode, url, console);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		final JButton btnUpload250 = new JButton(Label.BUTTON_UPLOAD_250.toString());
		
		btnUpload250.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						String url = getFile().getAbsolutePath();
						progress.setIndeterminate(true);
						if (url != null && (service.countHud250(year, countyCode) == 0 || JOptionPane.showConfirmDialog(frame, "資料庫已有" + year + "年的資料，確定要重新上傳？", "確認上傳", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == 0)) {
							startTime = System.currentTimeMillis();
							service.uploadHud250(year, countyCode, url, console);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		final JButton btnUploadPost = new JButton(Label.BUTTON_UPLOAD_POST.toString());
		
		btnUploadPost.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						String url = getFile().getAbsolutePath();
						if (url != null) {
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							service.uploadAdrPost(year, countyCode, url, console);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		final JButton btnUploadPost2 = new JButton(Label.BUTTON_UPLOAD_POST2.toString());
		
		btnUploadPost2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						String url = getFile().getAbsolutePath();
						if (url != null) {
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							service.uploadAdrPost2(year, countyCode, url, console);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		final JButton btnUploadArea = new JButton(Label.BUTTON_UPLOAD_AREA.toString());
		
		btnUploadArea.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						String url = getFile().getAbsolutePath();
						if (url != null) {
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							service.uploadAdrArea(countyCode, url, console);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnUploadSprd = new JButton(Label.BUTTON_UPLOAD_SPRD.toString());
		
		btnUploadSprd.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						String url = getFile().getAbsolutePath();
						if (url != null) {
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							service.uploadAdrSprd(countyCode, url, console);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnUploadWordMap = new JButton(Label.BUTTON_UPLOAD_WORD_MAP.toString());
		
		btnUploadWordMap.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						String url = getFile().getAbsolutePath();
						if (url != null) {
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							service.uploadWordMap(url, console);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		panelBot1.add(btnUpload200, "w 50%");
		panelBot1.add(btnUpload250, "w 50%, wrap");
		panelBot1.add(btnUploadPost, "w 50%");
		panelBot1.add(btnUploadArea, "w 50%, wrap");
		//panelBot1.add(btnUploadPost2, "w 50%");
		panelBot1.add(btnUploadSprd, "w 50%");
		panelBot1.add(btnUploadWordMap, "w 50%");
		
		
		final JPanel panelBot2 = new JPanel(new MigLayout());
		panelBot2.setBorder(BorderFactory.createTitledBorder("地址分欄"));

		final JButton btnTo380 = new JButton(Label.BUTTON_TO_380.toString());
		
		btnTo380.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						PartAddress partAddress = new PartAddress();
						startTime = System.currentTimeMillis();
						service.disableAdr380();
						service.deleteAdr380(year, countyCode);
						partAddress.part(year, countyCode, console);
						service.enableAdr380();
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutput380 = new JButton(Label.BUTTON_OUTPUT_380.toString());
		btnOutput380.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdr380(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		panelBot2.add(btnTo380, "w 50%");
		panelBot2.add(btnOutput380, "w 50%");
		
		panel1.add(panelTop1, "w 50%, h 50%");
		panel1.add(panelTop2, "w 50%, h 50%, wrap");
		panel1.add(panelBot1, "w 50%, h 50%");
		panel1.add(panelBot2, "w 50%, h 50%");
	}
	
	private void setPanel2() {
		final JPanel panelTop = new JPanel(new MigLayout());
		panelTop.setBorder(BorderFactory.createTitledBorder("年份"));
		final JComboBox<String> cbYear = new JComboBox<String>();
		Integer currentYear = calendar.get(Calendar.YEAR) - YEAR_DIFF;
		for (Integer year = currentYear - 4; year <= currentYear + 10; year++) {
			cbYear.addItem(year.toString());
		}
		cbYear.setSelectedItem(currentYear.toString());
		panelTop.add(cbYear, "w 100%");
		
		final JPanel panelBot = new JPanel(new MigLayout());
		panelBot.setBorder(BorderFactory.createTitledBorder("縣市"));
		final JComboBox<String> cbCounty = new JComboBox<String>();
		for (String key : countyMap.keySet()) {
			cbCounty.addItem(key);
		}
		panelBot.add(cbCounty, "w 100%");
		
		final JPanel panel = new JPanel(new MigLayout());
		panel.setBorder(BorderFactory.createTitledBorder("產製參考檔"));
		
		final JButton btnOutput220 = new JButton(Label.BUTTON_OUTPUT_220.toString());
		btnOutput220.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdr220(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutput260 = new JButton(Label.BUTTON_OUTPUT_260.toString());
		btnOutput260.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdr260(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutput270 = new JButton(Label.BUTTON_OUTPUT_270.toString());
		btnOutput270.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdr270(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutputPost = new JButton(Label.BUTTON_OUTPUT_POST.toString());
		btnOutputPost.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdrPost(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutputSprd = new JButton(Label.BUTTON_OUTPUT_SPRD.toString());
		btnOutputSprd.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdrSprd(year, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutputArea = new JButton(Label.BUTTON_OUTPUT_AREA.toString());
		btnOutputArea.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputArea(year, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutputCity = new JButton(Label.BUTTON_OUTPUT_CITY.toString());
		btnOutputCity.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputCity(year, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutput150 = new JButton(Label.BUTTON_OUTPUT_150.toString());
		
		btnOutput150.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						toggleTabbedPane(false);
						final String encoding = "MS950";
						String url = getFile().getAbsolutePath();
						if (url != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							progress.setIndeterminate(true);
							List<StreetBlockVO> list = sbService.readFile(url, encoding);
							final String outputUrl = OUTPUT_PATH + "鄰街廓/103." + DateUtils.getCurrentDate() + ".L150.txt";
							startTime = System.currentTimeMillis();
							sbService.output(list, outputUrl, encoding, StreetBlockVO.TYPE_NEIGHBORHOOD, console, false);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutput168 = new JButton(Label.BUTTON_OUTPUT_168.toString());
		
		btnOutput168.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						toggleTabbedPane(false);
						final String encoding = "MS950";
						String url = getFile().getAbsolutePath();
						if (url != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							progress.setIndeterminate(true);
							List<StreetBlockVO> list = sbService.readFile(url, encoding);
							final String outputUrl = OUTPUT_PATH + "村里街廓/103." + DateUtils.getCurrentDate() + ".L168.txt";
							startTime = System.currentTimeMillis();
							sbService.output(list, outputUrl, encoding, StreetBlockVO.TYPE_VILLAGE, console, false);
							endTime = System.currentTimeMillis();
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutput150New = new JButton(Label.BUTTON_OUTPUT_150NEW.toString());
		btnOutput150New.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdr150(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutput168New = new JButton(Label.BUTTON_OUTPUT_168NEW.toString());
		btnOutput168New.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputAdr168(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnOutputWordMap = new JButton(Label.BUTTON_OUTPUT_WORD_MAP.toString());
		btnOutputWordMap.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				final String year = String.valueOf(cbYear.getSelectedItem());
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						progress.setIndeterminate(true);
						toggleTabbedPane(false);
						startTime = System.currentTimeMillis();
						service.outputWordMap(year, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		panel.add(btnOutput260, "w 25%");
		panel.add(btnOutput270, "w 25%");
		panel.add(btnOutputPost, "w 25%");
		panel.add(btnOutputSprd, "w 25%, wrap");
		panel.add(btnOutputArea, "w 25%");
		panel.add(btnOutputCity, "w 25%");
		panel.add(btnOutput150, "w 25%");
		panel.add(btnOutput168, "w 25%, wrap");
		panel.add(btnOutput220, "w 25%");
		panel.add(btnOutput150New, "w 25%");
		panel.add(btnOutput168New, "w 25%");
		panel.add(btnOutputWordMap, "w 25%");
		
		panel2.add(panelTop, "w 50% ,h 50%");
		panel2.add(panelBot, "w 50% ,h 50%, wrap");
		panel2.add(panel, "w 100%, h 50%, span 2");
		
	}
	
	private void setPanel3() {
		final JPanel panelChoose = new JPanel(new MigLayout());
		panelChoose.setBorder(BorderFactory.createTitledBorder("選擇檔案"));
		
		final JButton btnSource = new JButton(Label.BUTTON_SOURCE.toString());
		final JLabel labelSource = new JLabel();
		btnSource.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				File file = getFile();
				if (file != null) {
					sourceUrl = file.getAbsolutePath();
					labelSource.setText(file.getName());
				}
			}
		});
		
		final JButton btnTarget = new JButton(Label.BUTTON_TARGET.toString());
		final JLabel labelTarget = new JLabel();
		btnTarget.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				File file = getFile();
				if (file != null) {
					targetUrl = file.getAbsolutePath();
					labelTarget.setText(file.getName());
				}
			}
		});
		
		panelChoose.add(btnSource, "w 50%");
		panelChoose.add(btnTarget, "w 50%, wrap");
		panelChoose.add(labelSource, "w 50%");
		panelChoose.add(labelTarget, "w 50%, wrap");
		
		final JPanel panelCompare = new JPanel(new MigLayout());
		panelCompare.setBorder(BorderFactory.createTitledBorder("比較類型"));
		
		final JButton btn150 = new JButton(Label.BUTTON_COMPARE_150.toString());
		btn150.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						if (sourceUrl != null && targetUrl != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							toggleTabbedPane(false);
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							console.append(service.compare(sourceUrl, targetUrl, 150) + "\n");
							endTime = System.currentTimeMillis();
						} else {
							JOptionPane.showConfirmDialog(frame, "請選擇檔案", "警告訊息", JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
						sourceUrl = null;
						targetUrl = null;
						labelSource.setText(null);
						labelTarget.setText(null);
					}
				};
				worker.execute();
			}
		});
		
		final JButton btn168 = new JButton(Label.BUTTON_COMPARE_168.toString());
		btn168.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						if (sourceUrl != null && targetUrl != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							toggleTabbedPane(false);
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							console.append(service.compare(sourceUrl, targetUrl, 168) + "\n");
							endTime = System.currentTimeMillis();
						} else {
							JOptionPane.showConfirmDialog(frame, "請選擇檔案", "警告訊息", JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
						sourceUrl = null;
						targetUrl = null;
						labelSource.setText(null);
						labelTarget.setText(null);
					}
				};
				worker.execute();
			}
		});
		
		final JButton btn260 = new JButton(Label.BUTTON_COMPARE_260.toString());
		btn260.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						if (sourceUrl != null && targetUrl != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							toggleTabbedPane(false);
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							console.append(service.compare(sourceUrl, targetUrl, 260) + "\n");
							endTime = System.currentTimeMillis();
						} else {
							JOptionPane.showConfirmDialog(frame, "請選擇檔案", "警告訊息", JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
						sourceUrl = null;
						targetUrl = null;
						labelSource.setText(null);
						labelTarget.setText(null);
					}
				};
				worker.execute();
			}
		});
		
		final JButton btn270 = new JButton(Label.BUTTON_COMPARE_270.toString());
		btn270.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						if (sourceUrl != null && targetUrl != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							toggleTabbedPane(false);
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							console.append(service.compare(sourceUrl, targetUrl, 270) + "\n");
							endTime = System.currentTimeMillis();
						} else {
							JOptionPane.showConfirmDialog(frame, "請選擇檔案", "警告訊息", JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
						sourceUrl = null;
						targetUrl = null;
						labelSource.setText(null);
						labelTarget.setText(null);
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnArea = new JButton(Label.BUTTON_COMPARE_AREA.toString());
		btnArea.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						if (sourceUrl != null && targetUrl != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							toggleTabbedPane(false);
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							console.append(service.compare(sourceUrl, targetUrl, 31) + "\n");
							endTime = System.currentTimeMillis();
						} else {
							JOptionPane.showConfirmDialog(frame, "請選擇檔案", "警告訊息", JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
						sourceUrl = null;
						targetUrl = null;
						labelSource.setText(null);
						labelTarget.setText(null);
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnPost = new JButton(Label.BUTTON_COMPARE_POST.toString());
		btnPost.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						if (sourceUrl != null && targetUrl != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							toggleTabbedPane(false);
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							console.append(service.compare(sourceUrl, targetUrl, 84) + "\n");
							endTime = System.currentTimeMillis();
						} else {
							JOptionPane.showConfirmDialog(frame, "請選擇檔案", "警告訊息", JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
						sourceUrl = null;
						targetUrl = null;
						labelSource.setText(null);
						labelTarget.setText(null);;
					}
				};
				worker.execute();
			}
		});
		
		final JButton btnSprd = new JButton(Label.BUTTON_COMPARE_SPRD.toString());
		btnSprd.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						if (sourceUrl != null && targetUrl != null) {
							frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
							toggleTabbedPane(false);
							progress.setIndeterminate(true);
							startTime = System.currentTimeMillis();
							console.append(service.compare(sourceUrl, targetUrl, 70) + "\n");
							endTime = System.currentTimeMillis();
						} else {
							JOptionPane.showConfirmDialog(frame, "請選擇檔案", "警告訊息", JOptionPane.CLOSED_OPTION, JOptionPane.WARNING_MESSAGE);
						}
						return null;
					}

					@Override
					protected void done() {
						finish();
						sourceUrl = null;
						targetUrl = null;
						labelSource.setText(null);
						labelTarget.setText(null);
					}
				};
				worker.execute();
			}
		});
		
		panelCompare.add(btn150, "w 120");
		panelCompare.add(btn168, "w 120");
		panelCompare.add(btn260, "w 120");
		panelCompare.add(btn270, "w 120, wrap");
		panelCompare.add(btnPost, "w 120");
		panelCompare.add(btnArea, "w 120");
		panelCompare.add(btnSprd, "w 120");
		
		
		panel3.add(panelChoose, "w 100%, h 50%, wrap");
		panel3.add(panelCompare, "w 100%, h 50%");
		
	}

	private File getFile() {
		JFileChooser chooser = new JFileChooser();
		int returnVal = chooser.showOpenDialog(frame);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			return chooser.getSelectedFile();
		}
		return null;
	}
	
	private Boolean toggleTabbedPane(Boolean enable) {
		tabbedPane.setEnabled(enable);
		setBusy(tabbedPane.getComponents(), enable);
		return true;
	}
	
	private Boolean setBusy(java.awt.Component[] components, Boolean enable) {
		for (java.awt.Component component : components) {
			if (component instanceof JComponent) {
				component.setEnabled(enable);
				java.awt.Component[] childs = ((JComponent) component).getComponents();
				if (childs.length > 0) {
					setBusy(childs, enable);
				}
			}
		}
		return true;
	}
	
	private void finish() {
		if (startTime > 0L) {
			console.append("...Done in " + (endTime - startTime) / 1000 + " sec.\n");
		}
		startTime = 0L;
		endTime = 0L;
		toggleTabbedPane(true);
		progress.setIndeterminate(false);
		frame.setCursor(Cursor.getDefaultCursor());
		worker = null;
	}
	
	private void setPanel4() {
		final JPanel panelTop1 = new JPanel(new MigLayout());
		panelTop1.setBorder(BorderFactory.createTitledBorder("年份"));
		Integer currentYear = calendar.get(Calendar.YEAR) - YEAR_DIFF;
		final JComboBox<String> cbYear = new JComboBox<String>();
		for (Integer year = currentYear - 4; year <= currentYear + 10; year++) {
			cbYear.addItem(year.toString());
		}
		cbYear.setSelectedItem(currentYear.toString());
		panelTop1.add(cbYear, "w 100%");
		
		final JPanel panelTop2 = new JPanel(new MigLayout());
		panelTop2.setBorder(BorderFactory.createTitledBorder("縣市"));
		final JComboBox<String> cbCounty = new JComboBox<String>();
		for (String key : countyMap.keySet()) {
			cbCounty.addItem(key);
		}
		panelTop2.add(cbCounty, "w 100%");
		
		final JPanel panelBot = new JPanel(new MigLayout());
		panelBot.setBorder(BorderFactory.createTitledBorder("維護街廓檔"));
		
		JButton btnCreate150 = new JButton(Label.BUTTON_CREATE_150.toString());
		btnCreate150.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						progress.setIndeterminate(true);
						startTime = System.currentTimeMillis();
						service.create150(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		JButton btnCreate168 = new JButton(Label.BUTTON_CREATE_168.toString());
		btnCreate168.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						progress.setIndeterminate(true);
						startTime = System.currentTimeMillis();
						service.create168(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		JButton btnCreate220 = new JButton(Label.BUTTON_CREATE_220.toString());
		btnCreate220.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						progress.setIndeterminate(true);
						startTime = System.currentTimeMillis();
						service.createAdr220(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		JButton btnInit220 = new JButton(Label.BUTTON_INIT_220.toString());
		btnInit220.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final String year = String.valueOf(cbYear.getSelectedItem());
				final String countyCode = countyMap.get(String.valueOf(cbCounty.getSelectedItem()));
				console.setText(null);
				worker = new SwingWorker<Void, Void> () {
					@Override
					protected Void doInBackground() throws Exception {
						frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
						toggleTabbedPane(false);
						progress.setIndeterminate(true);
						startTime = System.currentTimeMillis();
						service.initAdr220(year, countyCode, console);
						endTime = System.currentTimeMillis();
						return null;
					}

					@Override
					protected void done() {
						finish();
					}
				};
				worker.execute();
			}
		});
		
		panelBot.add(btnCreate150);
		panelBot.add(btnCreate168);
		panelBot.add(btnInit220);
		panelBot.add(btnCreate220);
		
		panel4.add(panelTop1, "w 50%, h 50%, push");
		panel4.add(panelTop2, "w 50%, h 50%, push, wrap");
		panel4.add(panelBot, "w 100%, h 50%, span 2");
		
	}
	
}
